"""
数据源相关的Pydantic模式定义
"""

from pydantic import BaseModel, validator
from typing import Optional, Dict, Any, List
from datetime import datetime
from enum import Enum
import json


class DataSourceType(str, Enum):
    """数据源类型枚举"""
    MYSQL = "mysql"
    CSV = "csv"
    EXCEL = "excel"


class MySQLConfig(BaseModel):
    """MySQL数据源配置"""
    host: str
    port: int = 3306
    database: str
    username: str
    password: str
    charset: str = "utf8mb4"
    
    @validator('port')
    def validate_port(cls, v):
        if not 1 <= v <= 65535:
            raise ValueError('端口号必须在1-65535之间')
        return v


class CSVConfig(BaseModel):
    """CSV数据源配置"""
    file_path: str
    encoding: str = "utf-8"
    delimiter: str = ","
    has_header: bool = True
    
    @validator('encoding')
    def validate_encoding(cls, v):
        valid_encodings = ['utf-8', 'gbk', 'gb2312', 'ascii', 'latin1']
        if v.lower() not in valid_encodings:
            raise ValueError(f'编码必须是以下之一: {", ".join(valid_encodings)}')
        return v.lower()


class ExcelConfig(BaseModel):
    """Excel数据源配置"""
    file_path: str
    sheet_name: Optional[str] = None  # None表示第一个sheet
    has_header: bool = True
    start_row: int = 0  # 从第几行开始读取（0-based）
    
    @validator('start_row')
    def validate_start_row(cls, v):
        if v < 0:
            raise ValueError('起始行号不能小于0')
        return v


class DataSourceCreate(BaseModel):
    """创建数据源请求模式"""
    name: str
    type: DataSourceType
    config: Dict[str, Any]
    description: Optional[str] = None
    
    @validator('name')
    def validate_name(cls, v):
        if not v or len(v.strip()) < 2:
            raise ValueError('数据源名称至少需要2个字符')
        return v.strip()
    
    @validator('config')
    def validate_config(cls, v, values):
        """根据数据源类型验证配置"""
        if 'type' not in values:
            return v
            
        data_type = values['type']
        try:
            if data_type == DataSourceType.MYSQL:
                MySQLConfig(**v)
            elif data_type == DataSourceType.CSV:
                CSVConfig(**v)
            elif data_type == DataSourceType.EXCEL:
                ExcelConfig(**v)
        except Exception as e:
            raise ValueError(f'配置验证失败: {str(e)}')
        return v


class DataSourceUpdate(BaseModel):
    """更新数据源请求模式"""
    name: Optional[str] = None
    config: Optional[Dict[str, Any]] = None
    description: Optional[str] = None
    
    @validator('name')
    def validate_name(cls, v):
        if v is not None and (not v or len(v.strip()) < 2):
            raise ValueError('数据源名称至少需要2个字符')
        return v.strip() if v else v


class DataSourceResponse(BaseModel):
    """数据源响应模式"""
    id: int
    name: str
    type: DataSourceType
    config: Dict[str, Any]
    description: Optional[str]
    user_id: int
    created_at: datetime
    updated_at: datetime

    @validator('config', pre=True)
    def parse_config(cls, v):
        """解析config字段，如果是字符串则转换为字典"""
        if isinstance(v, str):
            try:
                return json.loads(v)
            except json.JSONDecodeError:
                return {}
        return v

    class Config:
        from_attributes = True


class DataSourceList(BaseModel):
    """数据源列表响应模式"""
    items: List[DataSourceResponse]
    total: int
    page: int
    size: int
    pages: int


class ConnectionTestRequest(BaseModel):
    """连接测试请求模式"""
    type: DataSourceType
    config: Dict[str, Any]


class ConnectionTestResponse(BaseModel):
    """连接测试响应模式"""
    success: bool
    message: str
    details: Optional[Dict[str, Any]] = None


class DataPreviewRequest(BaseModel):
    """数据预览请求模式"""
    data_source_id: int
    limit: int = 10
    table_name: Optional[str] = None
    
    @validator('limit')
    def validate_limit(cls, v):
        if not 1 <= v <= 100:
            raise ValueError('预览行数必须在1-100之间')
        return v


class DataSourceTable(BaseModel):
    """数据源表信息"""
    name: str
    comment: Optional[str] = None
    row_count: Optional[int] = None


class DataSourceTablesResponse(BaseModel):
    """数据源表列表响应"""
    tables: List[DataSourceTable]
    total_count: int


class DataPreviewResponse(BaseModel):
    """数据预览响应模式"""
    columns: List[str]
    data: List[List[Any]]
    total_rows: Optional[int] = None
    sample_rows: int
    table_name: Optional[str] = None
